#include <physics/Box.h>
#include <box2d/dynamics/b2Fixture.h>
#include <box2d/collision/shapes/b2PolygonShape.h>

namespace physics
{

Box::Box(World *world)
	: Node(world)
{
}
	
Box::Box(World *world, float width, float height, const Vector2 & center)
	: Node(world)
	, width(width)
	, height(height)
{
	CreateDefaultBody();

	b2FixtureDef fd;
	fd.density = 1.0f;
	fd.friction = 0.0f;
	fd.restitution = 0.0f;

	b2PolygonShape shape;
	b2Vec2 b2Center = b2Vec2(center.x / GetWorldPixelsInMeter(), center.y / GetWorldPixelsInMeter());
	shape.SetAsBox(width / 2.0f / GetWorldPixelsInMeter(), height / 2.0f / GetWorldPixelsInMeter(), b2Center, 0.0f);

	fd.shape = &shape;
	body->CreateFixture(&fd);
}

std::auto_ptr <xml::ObjectANSI> Box::CreateLoader()
{
	return std::auto_ptr <xml::ObjectANSI> (new BoxLoader(this));
}

void Box::SetCenter(const Vector2 & center)
{
	b2PolygonShape * shape = reinterpret_cast<b2PolygonShape*>(GetBody()->GetFixtureList()->GetShape());
	
	float pixInM = GetWorldPixelsInMeter();
	shape->SetAsBox(width / 2.0f / pixInM, height / 2.0f / pixInM, b2Vec2(center.x / pixInM, center.y / pixInM), 0.0f);
}
	
Vector2 Box::GetCenter() const
{
	b2PolygonShape * shape = reinterpret_cast<b2PolygonShape*>(GetBody()->GetFixtureList()->GetShape());
	
	return Vector2(shape->m_centroid.x, shape->m_centroid.y) * GetWorldPixelsInMeter();
}
	
Vector2 Box::GetSize() const
{
	return Vector2(width, height);
}

// ------------------------------------------------------------------------------------
// ------------------------------------ Loader ----------------------------------------
// ------------------------------------------------------------------------------------

bool BoxLoader::on_attribute(xml::Provider *prov, const std::string &name, const std::string &value)
{
	if(name == "Width")
		return converter::convert(value, &GetNode()->width);
	if(name == "Height")
		return converter::convert(value, &GetNode()->height);
	if(name == "Center")
		return converter::convert(value, &center);
	if(name == "Size")
	{
		Vector2 size;
		if(!converter::convert(value, &size))
			return false;

		GetNode()->width = size.x;
		GetNode()->height = size.y;
		return true;
	}

	return NodeLoader::on_attribute(prov, name, value);
}

std::auto_ptr <b2Shape> BoxLoader::CreateShape()
{
	std::auto_ptr <b2PolygonShape> box(new b2PolygonShape());
	b2Vec2 b2Center = b2Vec2(center.x / node->GetWorldPixelsInMeter(), center.y / node->GetWorldPixelsInMeter());
	box->SetAsBox(GetNode()->width / 2.0f / node->GetWorldPixelsInMeter(), GetNode()->height / 2.0f / node->GetWorldPixelsInMeter(), b2Center, 0.0f);

	return std::auto_ptr <b2Shape>(box.release());
}

}	// namespace physics